package com.wj.gulimall.search.thread;

import java.util.concurrent.*;
import java.util.function.Function;

public class ThreadTest {

    //当前系统中只有一两个，每一个异步任务，提交给线程池让他自己去执行
    public static ExecutorService service = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws ExecutionException, InterruptedException {
/*        CompletableFuture<Integer> future =
                CompletableFuture.supplyAsync(() ->{
                    int i=1/0;
                    return 1;
                } , service)
                        //可以得到异常信息，但是没办法修改返回数据
                    .whenComplete((res,e)->System.out.println(res+":"+e))
                        //可以感知异常,同时可以修改返回数据
                    .exceptionally(e-> 10);*/
/*        CompletableFuture<Integer> future =
                CompletableFuture.supplyAsync(() ->{
                    int i=1/0;
                    return 1;
                } , service).handleAsync((r,e)->e==null?100:200,service);*/

/*        CompletableFuture future =
                CompletableFuture.supplyAsync(() ->1, service)
                    .thenAcceptAsync((i)-> {
                        System.out.println("执行完成"+":"+i);
                    },service);*/
        CompletableFuture<Integer> future1 =
                CompletableFuture.supplyAsync(() -> 1, service);
        CompletableFuture<Integer> future2 =
                CompletableFuture.supplyAsync(() -> 2, service);
        CompletableFuture<Integer> future = future1.applyToEitherAsync(future2, Function.identity(), service);
        System.out.println(future.get());
        service.shutdown();
    }

    public void test1() {

//        Thread01 thread01 = new Thread01();
//        thread01.start();
//        System.out.println("end");

//        Runable01 runable01 = new Runable01();
//        new Thread(runable01).start();

//        FutureTask<Integer> task = new FutureTask<>(new Callable01());
//        new Thread(task).start();
//        try {
//            System.out.println(task.get());
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
        /**
         * @see ThreadPoolExecutor
         * @see Executors
         * 七大参数：
         *   corePoolSize：核心线程数[一直存在，除非allowCoreThreadTimeOut]，创建好了就一直存在，等待接受任务去执行
         *   maximumPoolSize：最大线程数量；控制资源
         *   keepAliveTime：存活时间，如果当前正在运行的线程数量大于核心数量。
         *                  可以释放空闲线程（maximumPoolSize-corePoolSize）（线程空闲时间大于指定的keepAliveTime）
         *   unit：时间单位
         *   workQueue：阻塞队列，如果任务有很多，就将目前多的任务放在队列中
         *                      只要有线程空闲，就会去队列中取出新的任务去执行
         *   threadFactory：线程的创建工厂
         *   handler：如果当前阻塞队列满了，就会执行该策略拒绝任务
         *
         *   工作顺序：
         *   1）线程池创建，准备好核心线程，准备接收任务
         *   1.1 core满了，就将进来的任务放在阻塞队列中，空闲的core就会自己去阻塞队列中获取执行
         *   1.2 阻塞队列满了，就直接开启新线程执行，最大只能开启到maximumPoolSize的线程数目
         *   1.3 maximumPoolSize满了，就采用handler去拒绝任务
         *   1.4 maximumPoolSize都执行完成,就会有很多的线程空闲，在指定的时间keepAliveTime以后，释放maximumPoolSize-corePoolSize这些线程
         *
         *  常见四种线程池：
         *  newCachedThreadPool：创建一个可缓存的线程池，如果线程池长度超过处理需要，可灵活回收线程，若无可回收，则新建线程
         *  newFixedThreadPool：创建一个定长线程池，可控制最大并发数
         *  newScheduledThreadPool：创建一个定长线程池，支持定时及周期性任务执行
         *  newSingleThreadExecutor：创建一个单线程化的线程池，只有唯一一个线程来执行任务
         */
//        以上三种启动线程的方式都不用,将所有的异步任务都交给线程池执行
//            public ThreadPoolExecutor(int corePoolSize,
//                                      int maximumPoolSize,
//                                      long keepAliveTime,
//                                      TimeUnit unit,
//                                      BlockingQueue<Runnable> workQueue,
//                                      ThreadFactory threadFactory,
//                                      RejectedExecutionHandler handler)

        service.execute(() -> {
        });

    }

    public static class Thread01 extends Thread {
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println(i);
        }
    }

    public static class Runable01 implements Runnable {

        @Override
        public void run() {
            System.out.println(Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println(i);
        }
    }

    public static class Callable01 implements Callable<Integer> {

        @Override
        public Integer call() throws Exception {
            return 1 + 1;
        }
    }
}
